| ... |
... |
@@ -25,7 +25,7 @@ import GHC.Core.FamInstEnv |
|
25
|
25
|
import GHC.Core.Coercion
|
|
26
|
26
|
import GHC.Core.Predicate( EqRel(..) )
|
|
27
|
27
|
import GHC.Core.TyCon
|
|
28
|
|
-import GHC.Core.Unify( tcUnifyTyForInjectivity, typeListsAreApart, typesAreApart )
|
|
|
28
|
+import GHC.Core.Unify( tcUnifyTyForInjectivity, typeListsAreApart )
|
|
29
|
29
|
import GHC.Core.Coercion.Axiom
|
|
30
|
30
|
import GHC.Core.TyCo.Subst( elemSubst )
|
|
31
|
31
|
|
| ... |
... |
@@ -251,7 +251,7 @@ Consider T4254b: |
|
251
|
251
|
it doesn't matter which of the two we pick, but historically we have
|
|
252
|
252
|
picked the local-fundeps first.
|
|
253
|
253
|
|
|
254
|
|
- #14745 is another example
|
|
|
254
|
+ #14745 is another example. And #13651.
|
|
255
|
255
|
|
|
256
|
256
|
(DFL2) Try solving from top-level instances before fundeps.
|
|
257
|
257
|
From the definition `foo = op` we get
|
| ... |
... |
@@ -259,7 +259,7 @@ Consider T4254b: |
|
259
|
259
|
[W] FD Int Bool
|
|
260
|
260
|
We solve this from the top level instance before even trying fundeps.
|
|
261
|
261
|
If we did try fundeps, we'd generate [W] b ~ Bool, which fails.
|
|
262
|
|
- That doesn't matter -- failing fundep equalties are discarded -- but it's
|
|
|
262
|
+ That doesn't matter -- failing fundep equalities are discarded -- but it's
|
|
263
|
263
|
a waste of effort.
|
|
264
|
264
|
|
|
265
|
265
|
(DFL2) is achieved by trying fundeps only on /unsolved/ Wanteds.
|
| ... |
... |
@@ -463,24 +463,30 @@ by the extensive code in GHC.Builtin.Types.Literals. |
|
463
|
463
|
-}
|
|
464
|
464
|
|
|
465
|
465
|
tryEqFunDeps :: EqCt -> SolverStage ()
|
|
466
|
|
-tryEqFunDeps work_item@(EqCt { eq_lhs = lhs, eq_eq_rel = eq_rel })
|
|
|
466
|
+tryEqFunDeps work_item@(EqCt { eq_lhs = work_lhs
|
|
|
467
|
+ , eq_rhs = work_rhs
|
|
|
468
|
+ , eq_eq_rel = eq_rel })
|
|
467
|
469
|
| NomEq <- eq_rel
|
|
468
|
|
- , TyFamLHS tc args <- lhs
|
|
469
|
|
- = tryFamEqFunDeps tc args work_item -- We have F args ~ rhs
|
|
|
470
|
+ , TyFamLHS fam_tc work_args <- work_lhs -- We have F args ~N# rhs
|
|
|
471
|
+ = do { eqs_for_me <- simpleStage$ getInertFamEqsFor fam_tc work_args work_rhs
|
|
|
472
|
+ ; tryFamEqFunDeps eqs_for_me fam_tc work_args work_item }
|
|
470
|
473
|
| otherwise
|
|
471
|
474
|
= nopStage ()
|
|
472
|
475
|
|
|
473
|
476
|
|
|
474
|
|
-tryFamEqFunDeps :: TyCon -> [TcType] -> EqCt -> SolverStage ()
|
|
475
|
|
-tryFamEqFunDeps fam_tc args work_item@(EqCt { eq_ev = ev, eq_rhs = rhs })
|
|
|
477
|
+tryFamEqFunDeps :: [EqCt] -> TyCon -> [TcType] -> EqCt -> SolverStage ()
|
|
|
478
|
+tryFamEqFunDeps eqs_for_me fam_tc work_args
|
|
|
479
|
+ work_item@(EqCt { eq_ev = ev, eq_rhs = work_rhs })
|
|
476
|
480
|
| Just ops <- isBuiltInSynFamTyCon_maybe fam_tc
|
|
477
|
481
|
= if isGiven ev
|
|
478
|
|
- then tryGivenBuiltinFamEqFDs fam_tc ops args work_item
|
|
|
482
|
+ then tryGivenBuiltinFamEqFDs eqs_for_me fam_tc ops work_args work_item
|
|
479
|
483
|
else do { -- Note [Do local fundeps before top-level instances]
|
|
480
|
|
- tryFDEqns fam_tc args work_item $
|
|
481
|
|
- mkLocalBuiltinFamEqFDs fam_tc ops args rhs
|
|
482
|
|
- ; tryFDEqns fam_tc args work_item $
|
|
483
|
|
- mkTopBuiltinFamEqFDs fam_tc ops args rhs }
|
|
|
484
|
+ tryFDEqns fam_tc work_args work_item $
|
|
|
485
|
+ mkLocalBuiltinFamEqFDs eqs_for_me fam_tc ops work_args work_rhs
|
|
|
486
|
+ ; if null eqs_for_me
|
|
|
487
|
+ then tryFDEqns fam_tc work_args work_item $
|
|
|
488
|
+ mkTopBuiltinFamEqFDs fam_tc ops work_args work_rhs
|
|
|
489
|
+ else nopStage () }
|
|
484
|
490
|
|
|
485
|
491
|
| isGiven ev -- See (INJFAM:Given)
|
|
486
|
492
|
= nopStage ()
|
| ... |
... |
@@ -491,26 +497,31 @@ tryFamEqFunDeps fam_tc args work_item@(EqCt { eq_ev = ev, eq_rhs = rhs }) |
|
491
|
497
|
, Injective inj_flags <- tyConInjectivityInfo fam_tc
|
|
492
|
498
|
= -- Open, injective type families
|
|
493
|
499
|
do { -- Note [Do local fundeps before top-level instances]
|
|
494
|
|
- tryFDEqns fam_tc args work_item $
|
|
495
|
|
- mkLocalUserFamEqFDs fam_tc inj_flags args rhs
|
|
|
500
|
+ tryFDEqns fam_tc work_args work_item $
|
|
|
501
|
+ mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs
|
|
496
|
502
|
|
|
497
|
|
- ; tryFDEqns fam_tc args work_item $
|
|
498
|
|
- mkTopOpenFamEqFDs fam_tc inj_flags args rhs }
|
|
|
503
|
+ ; if null eqs_for_me
|
|
|
504
|
+ then tryFDEqns fam_tc work_args work_item $
|
|
|
505
|
+ mkTopOpenFamEqFDs fam_tc inj_flags work_args work_rhs
|
|
|
506
|
+ else nopStage () }
|
|
499
|
507
|
|
|
500
|
508
|
| Just ax <- isClosedFamilyTyCon_maybe fam_tc
|
|
501
|
509
|
= -- Closed type families
|
|
502
|
510
|
do { -- Note [Do local fundeps before top-level instances]
|
|
503
|
511
|
simpleStage $ traceTcS "fundep closed" (ppr fam_tc)
|
|
|
512
|
+
|
|
504
|
513
|
; case tyConInjectivityInfo fam_tc of
|
|
505
|
514
|
NotInjective -> nopStage()
|
|
506
|
|
- Injective inj -> tryFDEqns fam_tc args work_item $
|
|
507
|
|
- mkLocalUserFamEqFDs fam_tc inj args rhs
|
|
|
515
|
+ Injective inj -> tryFDEqns fam_tc work_args work_item $
|
|
|
516
|
+ mkLocalFamEqFDs eqs_for_me fam_tc inj work_args work_rhs
|
|
508
|
517
|
|
|
509
|
518
|
-- Now look at the top-level axioms; we effectively infer injectivity,
|
|
510
|
519
|
-- so we don't need tyConInjectivtyInfo. This works fine for closed
|
|
511
|
520
|
-- type families without injectivity info
|
|
512
|
|
- ; tryFDEqns fam_tc args work_item $
|
|
513
|
|
- mkTopClosedFamEqFDs ax args rhs }
|
|
|
521
|
+ ; if null eqs_for_me
|
|
|
522
|
+ then tryFDEqns fam_tc work_args work_item $
|
|
|
523
|
+ mkTopClosedFamEqFDs ax work_args work_rhs
|
|
|
524
|
+ else nopStage () }
|
|
514
|
525
|
|
|
515
|
526
|
| otherwise -- Data families, abstract families
|
|
516
|
527
|
= nopStage ()
|
| ... |
... |
@@ -542,7 +553,7 @@ mkTopClosedFamEqFDs ax work_args work_rhs |
|
542
|
553
|
go (branch : later_branches)
|
|
543
|
554
|
| CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys
|
|
544
|
555
|
, cab_rhs = rhs_ty, cab_incomps = incomps } <- branch
|
|
545
|
|
- , not (no_match lhs_tys rhs_ty)
|
|
|
556
|
+ , not (eqnIsApart lhs_tys rhs_ty work_args work_rhs)
|
|
546
|
557
|
= if all no_match_branch incomps && all no_match_branch later_branches
|
|
547
|
558
|
then [FDEqns { fd_qtvs = qtvs, fd_eqs = zipWith Pair lhs_tys work_args }]
|
|
548
|
559
|
else []
|
| ... |
... |
@@ -551,10 +562,7 @@ mkTopClosedFamEqFDs ax work_args work_rhs |
|
551
|
562
|
= go later_branches
|
|
552
|
563
|
|
|
553
|
564
|
no_match_branch (CoAxBranch { cab_lhs = lhs_tys, cab_rhs = rhs_ty })
|
|
554
|
|
- = no_match lhs_tys rhs_ty
|
|
555
|
|
-
|
|
556
|
|
- no_match lhs_tys rhs_ty = work_args `typeListsAreApart` lhs_tys ||
|
|
557
|
|
- work_rhs `typesAreApart` rhs_ty
|
|
|
565
|
+ = eqnIsApart lhs_tys rhs_ty work_args work_rhs
|
|
558
|
566
|
|
|
559
|
567
|
mkTopOpenFamEqFDs :: TyCon -> [Bool] -> [TcType] -> Xi -> TcS [FunDepEqns]
|
|
560
|
568
|
-- Implements (INJFAM:Wanted/top)
|
| ... |
... |
@@ -592,12 +600,10 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args work_rhs |
|
592
|
600
|
!(subst', tvs') = trim_qtvs subst1 tvs
|
|
593
|
601
|
in (subst', tv':tvs')
|
|
594
|
602
|
|
|
595
|
|
-mkLocalUserFamEqFDs :: TyCon -> [Bool] -> [TcType] -> Xi -> TcS [FunDepEqns]
|
|
596
|
|
-mkLocalUserFamEqFDs fam_tc inj_flags work_args work_rhs
|
|
597
|
|
- = do { fun_eqs_for_me <- getInertFamEqsFor fam_tc
|
|
598
|
|
-
|
|
599
|
|
- ; let -- eqns_from_inerts: see (INJFAM:Wanted/other)
|
|
600
|
|
- eqns_from_inerts = mapMaybe do_one fun_eqs_for_me
|
|
|
603
|
+mkLocalFamEqFDs :: [EqCt] -> TyCon -> [Bool] -> [TcType] -> Xi -> TcS [FunDepEqns]
|
|
|
604
|
+mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs
|
|
|
605
|
+ = do { let -- eqns_from_inerts: see (INJFAM:Wanted/other)
|
|
|
606
|
+ eqns_from_inerts = mapMaybe do_one eqs_for_me
|
|
601
|
607
|
-- eqns_from_self: see (INJFAM:Wanted/Self)
|
|
602
|
608
|
eqns_from_self = case tcSplitTyConApp_maybe work_rhs of
|
|
603
|
609
|
Just (tc,rhs_tys) | tc==fam_tc -> [mk_eqn rhs_tys]
|
| ... |
... |
@@ -617,14 +623,16 @@ mkLocalUserFamEqFDs fam_tc inj_flags work_args work_rhs |
|
617
|
623
|
-- Built-in type families
|
|
618
|
624
|
-----------------------------------------
|
|
619
|
625
|
|
|
620
|
|
-tryGivenBuiltinFamEqFDs :: TyCon -> BuiltInSynFamily -> [TcType] -> EqCt -> SolverStage ()
|
|
|
626
|
+tryGivenBuiltinFamEqFDs :: [EqCt] -> TyCon -> BuiltInSynFamily
|
|
|
627
|
+ -> [TcType] -> EqCt -> SolverStage ()
|
|
621
|
628
|
-- TyCon is definitely a built-in type family
|
|
622
|
629
|
-- Built-in type families are special becase we can generate
|
|
623
|
630
|
-- evidence from /Givens/. For example:
|
|
624
|
631
|
-- from [G] x+4~7 we can deduce [G] x~7
|
|
625
|
632
|
-- That's important!
|
|
626
|
633
|
-- See Note [Given/Given fundeps for built-in type families]
|
|
627
|
|
-tryGivenBuiltinFamEqFDs fam_tc ops work_args (EqCt { eq_ev = work_ev, eq_rhs = work_rhs })
|
|
|
634
|
+tryGivenBuiltinFamEqFDs eqs_for_me fam_tc ops work_args
|
|
|
635
|
+ (EqCt { eq_ev = work_ev, eq_rhs = work_rhs })
|
|
628
|
636
|
= Stage $
|
|
629
|
637
|
do { traceTcS "tryBuiltinFamEqFDs" $
|
|
630
|
638
|
vcat [ text "lhs:" <+> ppr fam_tc <+> ppr work_args
|
| ... |
... |
@@ -632,8 +640,7 @@ tryGivenBuiltinFamEqFDs fam_tc ops work_args (EqCt { eq_ev = work_ev, eq_rhs = w |
|
632
|
640
|
, text "work_ev:" <+> ppr work_ev ]
|
|
633
|
641
|
|
|
634
|
642
|
-- interact with inert Givens, emitting new Givens
|
|
635
|
|
- ; fun_eqs_for_me <- getInertFamEqsFor fam_tc
|
|
636
|
|
- ; mapM_ do_one fun_eqs_for_me
|
|
|
643
|
+ ; mapM_ do_one eqs_for_me
|
|
637
|
644
|
|
|
638
|
645
|
-- Interact with top-level instancs, emitting new Givens
|
|
639
|
646
|
; emitNewGivens (ctEvLoc work_ev) $
|
| ... |
... |
@@ -682,11 +689,10 @@ mkTopBuiltinFamEqFDs fam_tc ops work_args work_rhs |
|
682
|
689
|
= return [FDEqns { fd_qtvs = []
|
|
683
|
690
|
, fd_eqs = map snd $ tryInteractTopFam ops fam_tc work_args work_rhs }]
|
|
684
|
691
|
|
|
685
|
|
-mkLocalBuiltinFamEqFDs :: TyCon -> BuiltInSynFamily -> [TcType] -> Xi -> TcS [FunDepEqns]
|
|
686
|
|
-mkLocalBuiltinFamEqFDs fam_tc ops work_args work_rhs
|
|
687
|
|
- = do { fun_eqs_for_me <- getInertFamEqsFor fam_tc
|
|
688
|
|
-
|
|
689
|
|
- ; let do_one :: EqCt -> [FunDepEqns]
|
|
|
692
|
+mkLocalBuiltinFamEqFDs :: [EqCt] -> TyCon -> BuiltInSynFamily
|
|
|
693
|
+ -> [TcType] -> Xi -> TcS [FunDepEqns]
|
|
|
694
|
+mkLocalBuiltinFamEqFDs eqs_for_me fam_tc ops work_args work_rhs
|
|
|
695
|
+ = do { let do_one :: EqCt -> [FunDepEqns]
|
|
690
|
696
|
do_one (EqCt { eq_lhs = TyFamLHS _ inert_args, eq_rhs = inert_rhs })
|
|
691
|
697
|
| inert_rhs `tcEqType` work_rhs = [mk_eqn inert_args]
|
|
692
|
698
|
| otherwise = []
|
| ... |
... |
@@ -697,7 +703,7 @@ mkLocalBuiltinFamEqFDs fam_tc ops work_args work_rhs |
|
697
|
703
|
, fd_eqs = map snd $ tryInteractInertFam ops fam_tc
|
|
698
|
704
|
work_args iargs }
|
|
699
|
705
|
|
|
700
|
|
- ; let eqns_from_inerts = concatMap do_one fun_eqs_for_me
|
|
|
706
|
+ ; let eqns_from_inerts = concatMap do_one eqs_for_me
|
|
701
|
707
|
eqns_from_self = case tcSplitTyConApp_maybe work_rhs of
|
|
702
|
708
|
Just (tc,rhs_tys) | tc==fam_tc -> [mk_eqn rhs_tys]
|
|
703
|
709
|
_ -> []
|
| ... |
... |
@@ -717,16 +723,29 @@ mkInjectivityFDEqn inj_args qtvs lhs_args rhs_args |
|
717
|
723
|
eqs = [ Pair lhs_arg rhs_arg
|
|
718
|
724
|
| (True, lhs_arg, rhs_arg) <- zip3 inj_args lhs_args rhs_args ]
|
|
719
|
725
|
|
|
720
|
|
-getInertFamEqsFor :: TyCon -> TcS [EqCt] -- Returns a mixture of Given and Wanted
|
|
|
726
|
+getInertFamEqsFor :: TyCon -> [TcType] -> Xi -> TcS [EqCt]
|
|
|
727
|
+-- Returns a mixture of Given and Wanted
|
|
721
|
728
|
-- Look in the InertSet, and return all inert equalities
|
|
722
|
729
|
-- F tys ~N# rhs
|
|
723
|
730
|
-- where F is the specified TyCon
|
|
|
731
|
+-- But filter out ones that can't possibly help, is apart from the Wanted
|
|
724
|
732
|
-- Representational equalities don't interact with type family dependencies
|
|
725
|
|
-getInertFamEqsFor fam_tc
|
|
|
733
|
+getInertFamEqsFor fam_tc work_args work_rhs
|
|
726
|
734
|
= do { IC {inert_funeqs = funeqs } <- getInertCans
|
|
727
|
735
|
; return [ funeq_ct | equal_ct_list <- findFunEqsByTyCon funeqs fam_tc
|
|
728
|
|
- , funeq_ct <- equal_ct_list
|
|
729
|
|
- , NomEq == eq_eq_rel funeq_ct ] }
|
|
|
736
|
+ , funeq_ct@(EqCt { eq_eq_rel = eq_rel
|
|
|
737
|
+ , eq_lhs = TyFamLHS _ inert_args
|
|
|
738
|
+ , eq_rhs = inert_rhs })
|
|
|
739
|
+ <- equal_ct_list
|
|
|
740
|
+ , NomEq == eq_rel
|
|
|
741
|
+ , not (eqnIsApart inert_args inert_rhs work_args work_rhs) ] }
|
|
|
742
|
+
|
|
|
743
|
+eqnIsApart :: [TcType] -> TcType
|
|
|
744
|
+ -> [TcType] -> TcType
|
|
|
745
|
+ -> Bool
|
|
|
746
|
+eqnIsApart lhs_tys1 rhs_ty1 lhs_tys2 rhs_ty2
|
|
|
747
|
+ = (rhs_ty1:lhs_tys1) `typeListsAreApart` (rhs_ty2:lhs_tys2)
|
|
|
748
|
+
|
|
730
|
749
|
|
|
731
|
750
|
{- Note [Type inference for type families with injectivity]
|
|
732
|
751
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... |
... |
@@ -744,11 +763,11 @@ For /injective/, /user-defined/ type families |
|
744
|
763
|
- When F is a built-in type family, we can do better;
|
|
745
|
764
|
See Note [Given/Given fundeps for built-in type families]
|
|
746
|
765
|
|
|
747
|
|
-* (INJFAM:Wanted/Self) see `mkLocalUserFamEqFDs`
|
|
|
766
|
+* (INJFAM:Wanted/Self) see `mkLocalFamEqFDs`
|
|
748
|
767
|
work item: [W] F s1 s2 ~ F t1 t2
|
|
749
|
768
|
We can generate FunDepEqns: (s2 ~ t2)
|
|
750
|
769
|
|
|
751
|
|
-* (INJFAM:Wanted/other) see `mkLocalUserFamEqFDs`
|
|
|
770
|
+* (INJFAM:Wanted/other) see `mkLocalFamEqFDs`
|
|
752
|
771
|
work item: [W] F s1 s2 ~ rhs -- Wanted
|
|
753
|
772
|
inert: [G/W] F t2 t2 ~ rhs -- Same `rhs`, Given or Wanted
|
|
754
|
773
|
We can generate FunDepEqns: (s2 ~ t2)
|