Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/Tc/Solver/Dict.hs
    ... ... @@ -8,9 +8,6 @@ module GHC.Tc.Solver.Dict (
    8 8
       matchLocalInst, chooseInstance,
    
    9 9
       makeSuperClasses, mkStrictSuperClasses,
    
    10 10
       solveCallStack,    -- For GHC.Tc.Solver
    
    11
    -
    
    12
    -  -- * Functional dependencies
    
    13
    -  doDictFunDepImprovement
    
    14 11
       ) where
    
    15 12
     
    
    16 13
     import GHC.Prelude
    
    ... ... @@ -1379,346 +1376,6 @@ with the least superclass depth (see Note [Replacement vs keeping]),
    1379 1376
     but that doesn't work for the example from #22216.
    
    1380 1377
     -}
    
    1381 1378
     
    
    1382
    -{- *********************************************************************
    
    1383
    -*                                                                      *
    
    1384
    -*          Functional dependencies, instantiation of equations
    
    1385
    -*                                                                      *
    
    1386
    -************************************************************************
    
    1387
    -
    
    1388
    -When we spot an equality arising from a functional dependency,
    
    1389
    -we now use that equality (a "wanted") to rewrite the work-item
    
    1390
    -constraint right away.  This avoids two dangers
    
    1391
    -
    
    1392
    - Danger 1: If we send the original constraint on down the pipeline
    
    1393
    -           it may react with an instance declaration, and in delicate
    
    1394
    -           situations (when a Given overlaps with an instance) that
    
    1395
    -           may produce new insoluble goals: see #4952
    
    1396
    -
    
    1397
    - Danger 2: If we don't rewrite the constraint, it may re-react
    
    1398
    -           with the same thing later, and produce the same equality
    
    1399
    -           again --> termination worries.
    
    1400
    -
    
    1401
    -To achieve this required some refactoring of GHC.Tc.Instance.FunDeps (nicer
    
    1402
    -now!).
    
    1403
    -
    
    1404
    -Note [FunDep and implicit parameter reactions]
    
    1405
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1406
    -Currently, our story of interacting two dictionaries (or a dictionary
    
    1407
    -and top-level instances) for functional dependencies (including implicit
    
    1408
    -parameters), is that we simply produce new Wanted equalities.  So for example
    
    1409
    -
    
    1410
    -        class D a b | a -> b where ...
    
    1411
    -    Inert:
    
    1412
    -        [G] d1 : D Int Bool
    
    1413
    -    WorkItem:
    
    1414
    -        [W] d2 : D Int alpha
    
    1415
    -
    
    1416
    -    We generate the extra work item
    
    1417
    -        [W] cv : alpha ~ Bool
    
    1418
    -    where 'cv' is currently unused.  However, this new item can perhaps be
    
    1419
    -    spontaneously solved to become given and react with d2,
    
    1420
    -    discharging it in favour of a new constraint d2' thus:
    
    1421
    -        [W] d2' : D Int Bool
    
    1422
    -        d2 := d2' |> D Int cv
    
    1423
    -    Now d2' can be discharged from d1
    
    1424
    -
    
    1425
    -We could be more aggressive and try to *immediately* solve the dictionary
    
    1426
    -using those extra equalities.
    
    1427
    -
    
    1428
    -If that were the case with the same inert set and work item we might discard
    
    1429
    -d2 directly:
    
    1430
    -
    
    1431
    -        [W] cv : alpha ~ Bool
    
    1432
    -        d2 := d1 |> D Int cv
    
    1433
    -
    
    1434
    -But in general it's a bit painful to figure out the necessary coercion,
    
    1435
    -so we just take the first approach. Here is a better example. Consider:
    
    1436
    -    class C a b c | a -> b
    
    1437
    -And:
    
    1438
    -     [G] d1 : C T Int Char
    
    1439
    -     [W] d2 : C T beta Int
    
    1440
    -In this case, it's *not even possible* to solve the wanted immediately.
    
    1441
    -So we should simply output the functional dependency and add this guy
    
    1442
    -[but NOT its superclasses] back in the worklist. Even worse:
    
    1443
    -     [G] d1 : C T Int beta
    
    1444
    -     [W] d2: C T beta Int
    
    1445
    -Then it is solvable, but its very hard to detect this on the spot.
    
    1446
    -
    
    1447
    -It's exactly the same with implicit parameters, except that the
    
    1448
    -"aggressive" approach would be much easier to implement.
    
    1449
    -
    
    1450
    -Note [Fundeps with instances, and equality orientation]
    
    1451
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1452
    -This Note describes a delicate interaction that constrains the orientation of
    
    1453
    -equalities. This one is about fundeps, but the /exact/ same thing arises for
    
    1454
    -type-family injectivity constraints: see Note [Improvement orientation].
    
    1455
    -
    
    1456
    -doTopFunDepImprovement compares the constraint with all the instance
    
    1457
    -declarations, to see if we can produce any equalities. E.g
    
    1458
    -   class C2 a b | a -> b
    
    1459
    -   instance C Int Bool
    
    1460
    -Then the constraint (C Int ty) generates the equality [W] ty ~ Bool.
    
    1461
    -
    
    1462
    -There is a nasty corner in #19415 which led to the typechecker looping:
    
    1463
    -   class C s t b | s -> t
    
    1464
    -   instance ... => C (T kx x) (T ky y) Int
    
    1465
    -   T :: forall k. k -> Type
    
    1466
    -
    
    1467
    -   work_item: dwrk :: C (T @ka (a::ka)) (T @kb0 (b0::kb0)) Char
    
    1468
    -      where kb0, b0 are unification vars
    
    1469
    -
    
    1470
    -   ==> {doTopFunDepImprovement: compare work_item with instance,
    
    1471
    -        generate /fresh/ unification variables kfresh0, yfresh0,
    
    1472
    -        emit a new Wanted, and add dwrk to inert set}
    
    1473
    -
    
    1474
    -   Suppose we emit this new Wanted from the fundep:
    
    1475
    -       [W] T kb0 (b0::kb0) ~ T kfresh0 (yfresh0::kfresh0)
    
    1476
    -
    
    1477
    -   ==> {solve that equality kb0 := kfresh0, b0 := yfresh0}
    
    1478
    -   Now kick out dwrk, since it mentions kb0
    
    1479
    -   But now we are back to the start!  Loop!
    
    1480
    -
    
    1481
    -NB1: This example relies on an instance that does not satisfy the
    
    1482
    -     coverage condition (although it may satisfy the weak coverage
    
    1483
    -     condition), and hence whose fundeps generate fresh unification
    
    1484
    -     variables.  Not satisfying the coverage condition is known to
    
    1485
    -     lead to termination trouble, but in this case it's plain silly.
    
    1486
    -
    
    1487
    -NB2: In this example, the third parameter to C ensures that the
    
    1488
    -     instance doesn't actually match the Wanted, so we can't use it to
    
    1489
    -     solve the Wanted
    
    1490
    -
    
    1491
    -We solve the problem by (#21703):
    
    1492
    -
    
    1493
    -    carefully orienting the new Wanted so that all the
    
    1494
    -    freshly-generated unification variables are on the LHS.
    
    1495
    -
    
    1496
    -    Thus we call unifyWanteds on
    
    1497
    -       T kfresh0 (yfresh0::kfresh0) ~ T kb0 (b0::kb0)
    
    1498
    -    and /NOT/
    
    1499
    -       T kb0 (b0::kb0) ~ T kfresh0 (yfresh0::kfresh0)
    
    1500
    -
    
    1501
    -Now we'll unify kfresh0:=kb0, yfresh0:=b0, and all is well.  The general idea
    
    1502
    -is that we want to preferentially eliminate those freshly-generated
    
    1503
    -unification variables, rather than unifying older variables, which causes
    
    1504
    -kick-out etc.
    
    1505
    -
    
    1506
    -Keeping younger variables on the left also gives very minor improvement in
    
    1507
    -the compiler performance by having less kick-outs and allocations (-0.1% on
    
    1508
    -average).  Indeed Historical Note [Eliminate younger unification variables]
    
    1509
    -in GHC.Tc.Utils.Unify describes an earlier attempt to do so systematically,
    
    1510
    -apparently now in abeyance.
    
    1511
    -
    
    1512
    -But this is is a delicate solution. We must take care to /preserve/
    
    1513
    -orientation during solving. Wrinkles:
    
    1514
    -
    
    1515
    -(W1) We start with
    
    1516
    -       [W] T kfresh0 (yfresh0::kfresh0) ~ T kb0 (b0::kb0)
    
    1517
    -     Decompose to
    
    1518
    -       [W] kfresh0 ~ kb0
    
    1519
    -       [W] (yfresh0::kfresh0) ~ (b0::kb0)
    
    1520
    -     Preserve orientation when decomposing!!
    
    1521
    -
    
    1522
    -(W2) Suppose we happen to tackle the second Wanted from (W1)
    
    1523
    -     first. Then in canEqCanLHSHetero we emit a /kind/ equality, as
    
    1524
    -     well as a now-homogeneous type equality
    
    1525
    -       [W] kco : kfresh0 ~ kb0
    
    1526
    -       [W] (yfresh0::kfresh0) ~ (b0::kb0) |> (sym kco)
    
    1527
    -     Preserve orientation in canEqCanLHSHetero!!  (Failing to
    
    1528
    -     preserve orientation here was the immediate cause of #21703.)
    
    1529
    -
    
    1530
    -(W3) There is a potential interaction with the swapping done by
    
    1531
    -     GHC.Tc.Utils.Unify.swapOverTyVars.  We think it's fine, but it's
    
    1532
    -     a slight worry.  See especially Note [TyVar/TyVar orientation] in
    
    1533
    -     that module.
    
    1534
    -
    
    1535
    -The trouble is that "preserving orientation" is a rather global invariant,
    
    1536
    -and sometimes we definitely do want to swap (e.g. Int ~ alpha), so we don't
    
    1537
    -even have a precise statement of what the invariant is.  The advantage
    
    1538
    -of the preserve-orientation plan is that it is extremely cheap to implement,
    
    1539
    -and apparently works beautifully.
    
    1540
    -
    
    1541
    ---- Alternative plan (1) ---
    
    1542
    -Rather than have an ill-defined invariant, another possiblity is to
    
    1543
    -elminate those fresh unification variables at birth, when generating
    
    1544
    -the new fundep-inspired equalities.
    
    1545
    -
    
    1546
    -The key idea is to call `instFlexiX` in `emitFunDepWanteds` on only those
    
    1547
    -type variables that are guaranteed to give us some progress. This means we
    
    1548
    -have to locally (without calling emitWanteds) identify the type variables
    
    1549
    -that do not give us any progress.  In the above example, we _know_ that
    
    1550
    -emitting the two wanteds `kco` and `co` is fruitless.
    
    1551
    -
    
    1552
    -  Q: How do we identify such no-ops?
    
    1553
    -
    
    1554
    -  1. Generate a matching substitution from LHS to RHS
    
    1555
    -        ɸ = [kb0 :-> k0, b0 :->  y0]
    
    1556
    -  2. Call `instFlexiX` on only those type variables that do not appear in the domain of ɸ
    
    1557
    -        ɸ' = instFlexiX ɸ (tvs - domain ɸ)
    
    1558
    -  3. Apply ɸ' on LHS and then call emitWanteds
    
    1559
    -        unifyWanteds ... (subst ɸ' LHS) RHS
    
    1560
    -
    
    1561
    -Why will this work?  The matching substitution ɸ will be a best effort
    
    1562
    -substitution that gives us all the easy solutions. It can be generated with
    
    1563
    -modified version of `Core/Unify.unify_tys` where we run it in a matching mode
    
    1564
    -and never generate `SurelyApart` and always return a `MaybeApart Subst`
    
    1565
    -instead.
    
    1566
    -
    
    1567
    -The same alternative plan would work for type-family injectivity constraints:
    
    1568
    -see Note [Improvement orientation] in GHC.Tc.Solver.Equality.
    
    1569
    ---- End of Alternative plan (1) ---
    
    1570
    -
    
    1571
    ---- Alternative plan (2) ---
    
    1572
    -We could have a new flavour of TcTyVar (like `TauTv`, `TyVarTv` etc; see GHC.Tc.Utils.TcType.MetaInfo)
    
    1573
    -for the fresh unification variables introduced by functional dependencies.  Say `FunDepTv`.  Then in
    
    1574
    -GHC.Tc.Utils.Unify.swapOverTyVars we could arrange to keep a `FunDepTv` on the left if possible.
    
    1575
    -Looks possible, but it's one more complication.
    
    1576
    ---- End of Alternative plan (2) ---
    
    1577
    -
    
    1578
    -
    
    1579
    ---- Historical note: Failed Alternative Plan (3) ---
    
    1580
    -Previously we used a flag `cc_fundeps` in `CDictCan`. It would flip to False
    
    1581
    -once we used a fun dep to hint the solver to break and to stop emitting more
    
    1582
    -wanteds.  This solution was not complete, and caused a failures while trying
    
    1583
    -to solve for transitive functional dependencies (test case: T21703)
    
    1584
    --- End of Historical note: Failed Alternative Plan (3) --
    
    1585
    -
    
    1586
    -Note [Do fundeps last]
    
    1587
    -~~~~~~~~~~~~~~~~~~~~~~
    
    1588
    -Consider T4254b:
    
    1589
    -  class FD a b | a -> b where { op :: a -> b }
    
    1590
    -
    
    1591
    -  instance FD Int Bool
    
    1592
    -
    
    1593
    -  foo :: forall a b. (a~Int,FD a b) => a -> Bool
    
    1594
    -  foo = op
    
    1595
    -
    
    1596
    -(DFL1) Try local fundeps first.
    
    1597
    -  From the ambiguity check on the type signature we get
    
    1598
    -    [G] FD Int b
    
    1599
    -    [W] FD Int beta
    
    1600
    -  Interacting these gives beta:=b; then we start again and solve without
    
    1601
    -  trying fundeps between the new [W] FD Int b and the top-level instance.
    
    1602
    -  If we did, we'd generate [W] b ~ Bool, which fails.
    
    1603
    -
    
    1604
    -(DFL2) Try solving from top-level instances before fundeps
    
    1605
    -  From the definition `foo = op` we get
    
    1606
    -    [G] FD Int b
    
    1607
    -    [W] FD Int Bool
    
    1608
    -  We solve this from the top level instance before even trying fundeps.
    
    1609
    -  If we did try fundeps, we'd generate [W] b ~ Bool, which fails.
    
    1610
    -
    
    1611
    -
    
    1612
    -Note [Weird fundeps]
    
    1613
    -~~~~~~~~~~~~~~~~~~~~
    
    1614
    -Consider   class Het a b | a -> b where
    
    1615
    -              het :: m (f c) -> a -> m b
    
    1616
    -
    
    1617
    -           class GHet (a :: * -> *) (b :: * -> *) | a -> b
    
    1618
    -           instance            GHet (K a) (K [a])
    
    1619
    -           instance Het a b => GHet (K a) (K b)
    
    1620
    -
    
    1621
    -The two instances don't actually conflict on their fundeps,
    
    1622
    -although it's pretty strange.  So they are both accepted. Now
    
    1623
    -try   [W] GHet (K Int) (K Bool)
    
    1624
    -This triggers fundeps from both instance decls;
    
    1625
    -      [W] K Bool ~ K [a]
    
    1626
    -      [W] K Bool ~ K beta
    
    1627
    -And there's a risk of complaining about Bool ~ [a].  But in fact
    
    1628
    -the Wanted matches the second instance, so we never get as far
    
    1629
    -as the fundeps.
    
    1630
    -
    
    1631
    -#7875 is a case in point.
    
    1632
    --}
    
    1633
    -
    
    1634
    -doDictFunDepImprovement :: Cts -> TcS (Cts, Bool)
    
    1635
    --- (doDictFunDepImprovement inst_envs cts)
    
    1636
    ---   * Generate the fundeps from interacting the
    
    1637
    ---     top-level `inst_envs` with the constraints `cts`
    
    1638
    ---   * Do the unifications and return any unsolved constraints
    
    1639
    --- See Note [Fundeps with instances, and equality orientation]
    
    1640
    -doDictFunDepImprovement unsolved_wanteds
    
    1641
    -  = do { inerts <- getInertCans  -- The inert_dicts are all Givens
    
    1642
    -       ; inst_envs <- getInstEnvs
    
    1643
    -       ; (_, new_eqs, unifs) <- foldrM (do_one_dict inst_envs)
    
    1644
    -                                       (inert_dicts inerts, emptyBag, False)
    
    1645
    -                                       unsolved_wanteds
    
    1646
    -       ; return (new_eqs, unifs) }
    
    1647
    -
    
    1648
    -do_one_dict :: InstEnvs -> Ct
    
    1649
    -            -> (DictMap DictCt, Cts, Bool)
    
    1650
    -            -> TcS (DictMap DictCt, Cts, Bool)
    
    1651
    -do_one_dict inst_envs (CDictCan dict_ct) (local_dicts, new_eqs, unifs)
    
    1652
    -  = do { (new_eqs1, unifs1) <- do_one_top inst_envs dict_ct
    
    1653
    -       ; (local_dicts2, new_eqs2, unifs2) <- do_one_local local_dicts dict_ct
    
    1654
    -       ; return ( local_dicts2
    
    1655
    -                , new_eqs1 `unionBags` new_eqs2 `unionBags` new_eqs
    
    1656
    -                , unifs1 || unifs2 || unifs ) }
    
    1657
    -
    
    1658
    -do_one_dict _ _ acc  -- Non-DictCt constraints
    
    1659
    -  = return acc
    
    1660
    -
    
    1661
    -do_one_top :: InstEnvs -> DictCt -> TcS (Cts, Bool)
    
    1662
    -do_one_top inst_envs (DictCt { di_ev = ev, di_cls = cls, di_tys = xis })
    
    1663
    -  = unifyFunDepWanteds ev eqns
    
    1664
    -  where
    
    1665
    -    eqns :: [FunDepEqn (CtLoc, RewriterSet)]
    
    1666
    -    eqns = improveFromInstEnv inst_envs mk_ct_loc cls xis
    
    1667
    -
    
    1668
    -    dict_pred      = mkClassPred cls xis
    
    1669
    -    dict_loc       = ctEvLoc ev
    
    1670
    -    dict_origin    = ctLocOrigin dict_loc
    
    1671
    -    dict_rewriters = ctEvRewriters ev
    
    1672
    -
    
    1673
    -    mk_ct_loc :: ClsInst  -- The instance decl
    
    1674
    -              -> (CtLoc, RewriterSet)
    
    1675
    -    mk_ct_loc ispec
    
    1676
    -      = (dict_loc { ctl_origin = new_orig }, dict_rewriters)
    
    1677
    -      where
    
    1678
    -        inst_pred = mkClassPred cls (is_tys ispec)
    
    1679
    -        inst_loc  = getSrcSpan (is_dfun ispec)
    
    1680
    -        new_orig  = FunDepOrigin2 dict_pred dict_origin
    
    1681
    -                                  inst_pred inst_loc
    
    1682
    -
    
    1683
    -do_one_local :: DictMap DictCt -> DictCt -> TcS (DictMap DictCt, Cts, Bool)
    
    1684
    --- Using functional dependencies, interact the unsolved Wanteds
    
    1685
    --- against each other and the inert Givens, to produce new equalities
    
    1686
    -do_one_local locals dict_ct@(DictCt { di_cls = cls, di_ev = wanted_ev })
    
    1687
    -    -- locals contains all the Givens and earlier Wanteds
    
    1688
    -  = do { (new_eqs, unifs) <- foldrM do_interaction (emptyBag, False) $
    
    1689
    -                             findDictsByClass locals cls
    
    1690
    -       ; return (addDict dict_ct locals, new_eqs, unifs) }
    
    1691
    -  where
    
    1692
    -    wanted_pred = ctEvPred wanted_ev
    
    1693
    -    wanted_loc  = ctEvLoc  wanted_ev
    
    1694
    -
    
    1695
    -    do_interaction :: DictCt -> (Cts,Bool) -> TcS (Cts,Bool)
    
    1696
    -    do_interaction (DictCt { di_ev = all_ev }) (new_eqs, unifs) -- This can be Given or Wanted
    
    1697
    -      = do { traceTcS "doLocalFunDepImprovement" $
    
    1698
    -             vcat [ ppr wanted_ev
    
    1699
    -                  , pprCtLoc wanted_loc, ppr (isGivenLoc wanted_loc)
    
    1700
    -                  , pprCtLoc all_loc, ppr (isGivenLoc all_loc)
    
    1701
    -                  , pprCtLoc deriv_loc, ppr (isGivenLoc deriv_loc) ]
    
    1702
    -
    
    1703
    -           ; (new_eqs1, unifs1) <- unifyFunDepWanteds wanted_ev $
    
    1704
    -                                   improveFromAnother (deriv_loc, all_rewriters)
    
    1705
    -                                                      all_pred wanted_pred
    
    1706
    -           ; return (new_eqs1 `unionBags` new_eqs, unifs1 || unifs) }
    
    1707
    -      where
    
    1708
    -        all_pred  = ctEvPred all_ev
    
    1709
    -        all_loc   = ctEvLoc all_ev
    
    1710
    -        all_rewriters = ctEvRewriters all_ev
    
    1711
    -        deriv_loc = wanted_loc { ctl_depth  = deriv_depth
    
    1712
    -                               , ctl_origin = deriv_origin }
    
    1713
    -        deriv_depth = ctl_depth wanted_loc `maxSubGoalDepth`
    
    1714
    -                      ctl_depth all_loc
    
    1715
    -        deriv_origin = FunDepOrigin1 wanted_pred
    
    1716
    -                                     (ctLocOrigin wanted_loc)
    
    1717
    -                                     (ctLocSpan wanted_loc)
    
    1718
    -                                     all_pred
    
    1719
    -                                     (ctLocOrigin all_loc)
    
    1720
    -                                     (ctLocSpan all_loc)
    
    1721
    -
    
    1722 1379
     
    
    1723 1380
     {- *********************************************************************
    
    1724 1381
     *                                                                      *
    

  • compiler/GHC/Tc/Solver/Equality.hs
    ... ... @@ -14,6 +14,7 @@ import GHC.Tc.Solver.Irred( solveIrred )
    14 14
     import GHC.Tc.Solver.Dict( matchLocalInst, chooseInstance )
    
    15 15
     import GHC.Tc.Solver.Rewrite
    
    16 16
     import GHC.Tc.Solver.Monad
    
    17
    +import GHC.Tc.Solver.FunDeps( unifyAndEmitFunDepWanteds )
    
    17 18
     import GHC.Tc.Solver.InertSet
    
    18 19
     import GHC.Tc.Solver.Types( findFunEqsByTyCon )
    
    19 20
     import GHC.Tc.Types.Evidence
    
    ... ... @@ -3108,13 +3109,17 @@ improve_wanted_top_fun_eqs fam_tc lhs_tys rhs_ty
    3108 3109
       | Just ops <- isBuiltInSynFamTyCon_maybe fam_tc
    
    3109 3110
       = return (map snd $ tryInteractTopFam ops fam_tc lhs_tys rhs_ty)
    
    3110 3111
     
    
    3112
    +  -- ToDo: use ideas in #23162 for closed type families; injectivity only for open
    
    3113
    +
    
    3111 3114
       -- See Note [Type inference for type families with injectivity]
    
    3115
    +  -- Open, so look for inj
    
    3112 3116
       | Injective inj_args <- tyConInjectivityInfo fam_tc
    
    3113 3117
       = do { fam_envs <- getFamInstEnvs
    
    3114 3118
            ; top_eqns <- improve_injective_wanted_top fam_envs inj_args fam_tc lhs_tys rhs_ty
    
    3115 3119
            ; let local_eqns = improve_injective_wanted_famfam  inj_args fam_tc lhs_tys rhs_ty
    
    3116 3120
            ; traceTcS "improve_wanted_top_fun_eqs" $
    
    3117 3121
              vcat [ ppr fam_tc, text "local_eqns" <+> ppr local_eqns, text "top_eqns" <+> ppr top_eqns ]
    
    3122
    +  -- xxx ToDo: this does both local and top => bug?
    
    3118 3123
            ; return (local_eqns ++ top_eqns) }
    
    3119 3124
     
    
    3120 3125
       | otherwise  -- No injectivity
    

  • compiler/GHC/Tc/Solver/FunDeps.hs
    1
    +{-# LANGUAGE DuplicateRecordFields #-}
    
    2
    +{-# LANGUAGE MultiWayIf #-}
    
    3
    +
    
    4
    +-- | Solving Class constraints CDictCan
    
    5
    +module GHC.Tc.Solver.FunDeps (
    
    6
    +  unifyAndEmitFunDepWanteds,
    
    7
    +  doDictFunDepImprovement,
    
    8
    +  ImprovementResult, noImprovement
    
    9
    +  ) where
    
    10
    +
    
    11
    +import GHC.Prelude
    
    12
    +
    
    13
    +import GHC.Tc.Instance.FunDeps
    
    14
    +import GHC.Tc.Types.Evidence
    
    15
    +import GHC.Tc.Types.Constraint
    
    16
    +import GHC.Tc.Types.CtLoc
    
    17
    +import GHC.Tc.Types.Origin
    
    18
    +import GHC.Tc.Solver.InertSet
    
    19
    +import GHC.Tc.Solver.Monad
    
    20
    +import GHC.Tc.Solver.Types
    
    21
    +import GHC.Tc.Utils.TcType
    
    22
    +import GHC.Tc.Utils.Unify( UnifyEnv(..) )
    
    23
    +import GHC.Tc.Utils.Monad    as TcM
    
    24
    +
    
    25
    +import GHC.Core.Type
    
    26
    +import GHC.Core.InstEnv     ( InstEnvs, ClsInst(..) )
    
    27
    +import GHC.Core.Coercion.Axiom( TypeEqn )
    
    28
    +
    
    29
    +import GHC.Types.Name
    
    30
    +import GHC.Types.Var.Set
    
    31
    +
    
    32
    +import GHC.Utils.Outputable
    
    33
    +
    
    34
    +import GHC.Data.Bag
    
    35
    +import GHC.Data.Pair
    
    36
    +
    
    37
    +import qualified Data.Semigroup as S
    
    38
    +
    
    39
    +import Control.Monad
    
    40
    +
    
    41
    +{- *********************************************************************
    
    42
    +*                                                                      *
    
    43
    +*          Functional dependencies, instantiation of equations
    
    44
    +*                                                                      *
    
    45
    +************************************************************************
    
    46
    +
    
    47
    +When we spot an equality arising from a functional dependency,
    
    48
    +we now use that equality (a "wanted") to rewrite the work-item
    
    49
    +constraint right away.  This avoids two dangers
    
    50
    +
    
    51
    + Danger 1: If we send the original constraint on down the pipeline
    
    52
    +           it may react with an instance declaration, and in delicate
    
    53
    +           situations (when a Given overlaps with an instance) that
    
    54
    +           may produce new insoluble goals: see #4952
    
    55
    +
    
    56
    + Danger 2: If we don't rewrite the constraint, it may re-react
    
    57
    +           with the same thing later, and produce the same equality
    
    58
    +           again --> termination worries.
    
    59
    +
    
    60
    +To achieve this required some refactoring of GHC.Tc.Instance.FunDeps (nicer
    
    61
    +now!).
    
    62
    +
    
    63
    +Note [FunDep and implicit parameter reactions]
    
    64
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    65
    +Currently, our story of interacting two dictionaries (or a dictionary
    
    66
    +and top-level instances) for functional dependencies (including implicit
    
    67
    +parameters), is that we simply produce new Wanted equalities.  So for example
    
    68
    +
    
    69
    +        class D a b | a -> b where ...
    
    70
    +    Inert:
    
    71
    +        [G] d1 : D Int Bool
    
    72
    +    WorkItem:
    
    73
    +        [W] d2 : D Int alpha
    
    74
    +
    
    75
    +    We generate the extra work item
    
    76
    +        [W] cv : alpha ~ Bool
    
    77
    +    where 'cv' is currently unused.  However, this new item can perhaps be
    
    78
    +    spontaneously solved to become given and react with d2,
    
    79
    +    discharging it in favour of a new constraint d2' thus:
    
    80
    +        [W] d2' : D Int Bool
    
    81
    +        d2 := d2' |> D Int cv
    
    82
    +    Now d2' can be discharged from d1
    
    83
    +
    
    84
    +We could be more aggressive and try to *immediately* solve the dictionary
    
    85
    +using those extra equalities.
    
    86
    +
    
    87
    +If that were the case with the same inert set and work item we might discard
    
    88
    +d2 directly:
    
    89
    +
    
    90
    +        [W] cv : alpha ~ Bool
    
    91
    +        d2 := d1 |> D Int cv
    
    92
    +
    
    93
    +But in general it's a bit painful to figure out the necessary coercion,
    
    94
    +so we just take the first approach. Here is a better example. Consider:
    
    95
    +    class C a b c | a -> b
    
    96
    +And:
    
    97
    +     [G] d1 : C T Int Char
    
    98
    +     [W] d2 : C T beta Int
    
    99
    +In this case, it's *not even possible* to solve the wanted immediately.
    
    100
    +So we should simply output the functional dependency and add this guy
    
    101
    +[but NOT its superclasses] back in the worklist. Even worse:
    
    102
    +     [G] d1 : C T Int beta
    
    103
    +     [W] d2: C T beta Int
    
    104
    +Then it is solvable, but its very hard to detect this on the spot.
    
    105
    +
    
    106
    +It's exactly the same with implicit parameters, except that the
    
    107
    +"aggressive" approach would be much easier to implement.
    
    108
    +
    
    109
    +Note [Fundeps with instances, and equality orientation]
    
    110
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    111
    +This Note describes a delicate interaction that constrains the orientation of
    
    112
    +equalities. This one is about fundeps, but the /exact/ same thing arises for
    
    113
    +type-family injectivity constraints: see Note [Improvement orientation].
    
    114
    +
    
    115
    +doTopFunDepImprovement compares the constraint with all the instance
    
    116
    +declarations, to see if we can produce any equalities. E.g
    
    117
    +   class C2 a b | a -> b
    
    118
    +   instance C Int Bool
    
    119
    +Then the constraint (C Int ty) generates the equality [W] ty ~ Bool.
    
    120
    +
    
    121
    +There is a nasty corner in #19415 which led to the typechecker looping:
    
    122
    +   class C s t b | s -> t
    
    123
    +   instance ... => C (T kx x) (T ky y) Int
    
    124
    +   T :: forall k. k -> Type
    
    125
    +
    
    126
    +   work_item: dwrk :: C (T @ka (a::ka)) (T @kb0 (b0::kb0)) Char
    
    127
    +      where kb0, b0 are unification vars
    
    128
    +
    
    129
    +   ==> {doTopFunDepImprovement: compare work_item with instance,
    
    130
    +        generate /fresh/ unification variables kfresh0, yfresh0,
    
    131
    +        emit a new Wanted, and add dwrk to inert set}
    
    132
    +
    
    133
    +   Suppose we emit this new Wanted from the fundep:
    
    134
    +       [W] T kb0 (b0::kb0) ~ T kfresh0 (yfresh0::kfresh0)
    
    135
    +
    
    136
    +   ==> {solve that equality kb0 := kfresh0, b0 := yfresh0}
    
    137
    +   Now kick out dwrk, since it mentions kb0
    
    138
    +   But now we are back to the start!  Loop!
    
    139
    +
    
    140
    +NB1: This example relies on an instance that does not satisfy the
    
    141
    +     coverage condition (although it may satisfy the weak coverage
    
    142
    +     condition), and hence whose fundeps generate fresh unification
    
    143
    +     variables.  Not satisfying the coverage condition is known to
    
    144
    +     lead to termination trouble, but in this case it's plain silly.
    
    145
    +
    
    146
    +NB2: In this example, the third parameter to C ensures that the
    
    147
    +     instance doesn't actually match the Wanted, so we can't use it to
    
    148
    +     solve the Wanted
    
    149
    +
    
    150
    +We solve the problem by (#21703):
    
    151
    +
    
    152
    +    carefully orienting the new Wanted so that all the
    
    153
    +    freshly-generated unification variables are on the LHS.
    
    154
    +
    
    155
    +    Thus we call unifyWanteds on
    
    156
    +       T kfresh0 (yfresh0::kfresh0) ~ T kb0 (b0::kb0)
    
    157
    +    and /NOT/
    
    158
    +       T kb0 (b0::kb0) ~ T kfresh0 (yfresh0::kfresh0)
    
    159
    +
    
    160
    +Now we'll unify kfresh0:=kb0, yfresh0:=b0, and all is well.  The general idea
    
    161
    +is that we want to preferentially eliminate those freshly-generated
    
    162
    +unification variables, rather than unifying older variables, which causes
    
    163
    +kick-out etc.
    
    164
    +
    
    165
    +Keeping younger variables on the left also gives very minor improvement in
    
    166
    +the compiler performance by having less kick-outs and allocations (-0.1% on
    
    167
    +average).  Indeed Historical Note [Eliminate younger unification variables]
    
    168
    +in GHC.Tc.Utils.Unify describes an earlier attempt to do so systematically,
    
    169
    +apparently now in abeyance.
    
    170
    +
    
    171
    +But this is is a delicate solution. We must take care to /preserve/
    
    172
    +orientation during solving. Wrinkles:
    
    173
    +
    
    174
    +(W1) We start with
    
    175
    +       [W] T kfresh0 (yfresh0::kfresh0) ~ T kb0 (b0::kb0)
    
    176
    +     Decompose to
    
    177
    +       [W] kfresh0 ~ kb0
    
    178
    +       [W] (yfresh0::kfresh0) ~ (b0::kb0)
    
    179
    +     Preserve orientation when decomposing!!
    
    180
    +
    
    181
    +(W2) Suppose we happen to tackle the second Wanted from (W1)
    
    182
    +     first. Then in canEqCanLHSHetero we emit a /kind/ equality, as
    
    183
    +     well as a now-homogeneous type equality
    
    184
    +       [W] kco : kfresh0 ~ kb0
    
    185
    +       [W] (yfresh0::kfresh0) ~ (b0::kb0) |> (sym kco)
    
    186
    +     Preserve orientation in canEqCanLHSHetero!!  (Failing to
    
    187
    +     preserve orientation here was the immediate cause of #21703.)
    
    188
    +
    
    189
    +(W3) There is a potential interaction with the swapping done by
    
    190
    +     GHC.Tc.Utils.Unify.swapOverTyVars.  We think it's fine, but it's
    
    191
    +     a slight worry.  See especially Note [TyVar/TyVar orientation] in
    
    192
    +     that module.
    
    193
    +
    
    194
    +The trouble is that "preserving orientation" is a rather global invariant,
    
    195
    +and sometimes we definitely do want to swap (e.g. Int ~ alpha), so we don't
    
    196
    +even have a precise statement of what the invariant is.  The advantage
    
    197
    +of the preserve-orientation plan is that it is extremely cheap to implement,
    
    198
    +and apparently works beautifully.
    
    199
    +
    
    200
    +--- Alternative plan (1) ---
    
    201
    +Rather than have an ill-defined invariant, another possiblity is to
    
    202
    +elminate those fresh unification variables at birth, when generating
    
    203
    +the new fundep-inspired equalities.
    
    204
    +
    
    205
    +The key idea is to call `instFlexiX` in `emitFunDepWanteds` on only those
    
    206
    +type variables that are guaranteed to give us some progress. This means we
    
    207
    +have to locally (without calling emitWanteds) identify the type variables
    
    208
    +that do not give us any progress.  In the above example, we _know_ that
    
    209
    +emitting the two wanteds `kco` and `co` is fruitless.
    
    210
    +
    
    211
    +  Q: How do we identify such no-ops?
    
    212
    +
    
    213
    +  1. Generate a matching substitution from LHS to RHS
    
    214
    +        ɸ = [kb0 :-> k0, b0 :->  y0]
    
    215
    +  2. Call `instFlexiX` on only those type variables that do not appear in the domain of ɸ
    
    216
    +        ɸ' = instFlexiX ɸ (tvs - domain ɸ)
    
    217
    +  3. Apply ɸ' on LHS and then call emitWanteds
    
    218
    +        unifyWanteds ... (subst ɸ' LHS) RHS
    
    219
    +
    
    220
    +Why will this work?  The matching substitution ɸ will be a best effort
    
    221
    +substitution that gives us all the easy solutions. It can be generated with
    
    222
    +modified version of `Core/Unify.unify_tys` where we run it in a matching mode
    
    223
    +and never generate `SurelyApart` and always return a `MaybeApart Subst`
    
    224
    +instead.
    
    225
    +
    
    226
    +The same alternative plan would work for type-family injectivity constraints:
    
    227
    +see Note [Improvement orientation] in GHC.Tc.Solver.Equality.
    
    228
    +--- End of Alternative plan (1) ---
    
    229
    +
    
    230
    +--- Alternative plan (2) ---
    
    231
    +We could have a new flavour of TcTyVar (like `TauTv`, `TyVarTv` etc; see GHC.Tc.Utils.TcType.MetaInfo)
    
    232
    +for the fresh unification variables introduced by functional dependencies.  Say `FunDepTv`.  Then in
    
    233
    +GHC.Tc.Utils.Unify.swapOverTyVars we could arrange to keep a `FunDepTv` on the left if possible.
    
    234
    +Looks possible, but it's one more complication.
    
    235
    +--- End of Alternative plan (2) ---
    
    236
    +
    
    237
    +
    
    238
    +--- Historical note: Failed Alternative Plan (3) ---
    
    239
    +Previously we used a flag `cc_fundeps` in `CDictCan`. It would flip to False
    
    240
    +once we used a fun dep to hint the solver to break and to stop emitting more
    
    241
    +wanteds.  This solution was not complete, and caused a failures while trying
    
    242
    +to solve for transitive functional dependencies (test case: T21703)
    
    243
    +-- End of Historical note: Failed Alternative Plan (3) --
    
    244
    +
    
    245
    +Note [Do fundeps last]
    
    246
    +~~~~~~~~~~~~~~~~~~~~~~
    
    247
    +Consider T4254b:
    
    248
    +  class FD a b | a -> b where { op :: a -> b }
    
    249
    +
    
    250
    +  instance FD Int Bool
    
    251
    +
    
    252
    +  foo :: forall a b. (a~Int,FD a b) => a -> Bool
    
    253
    +  foo = op
    
    254
    +
    
    255
    +(DFL1) Try local fundeps first.
    
    256
    +  From the ambiguity check on the type signature we get
    
    257
    +    [G] FD Int b
    
    258
    +    [W] FD Int beta
    
    259
    +  If we ineract that Wanted with /both/ the t0p-level instance, /and/ the
    
    260
    +  local Given, we'll get
    
    261
    +      beta ~ Int   and     beta ~ b
    
    262
    +  respectively.  That would generate (b~Bool), which would fai.  I think
    
    263
    +  it doesn't matter which of the two we pick, but historically we have
    
    264
    +  picked teh local-fundeps firs.
    
    265
    +
    
    266
    +(DFL2) Try solving from top-level instances before fundeps.
    
    267
    +  From the definition `foo = op` we get
    
    268
    +    [G] FD Int b
    
    269
    +    [W] FD Int Bool
    
    270
    +  We solve this from the top level instance before even trying fundeps.
    
    271
    +  If we did try fundeps, we'd generate [W] b ~ Bool, which fails.
    
    272
    +
    
    273
    +  (DFL2) is achieved by trying fundeps only on /unsolved/ Wanteds.
    
    274
    +
    
    275
    +
    
    276
    +Note [Weird fundeps]
    
    277
    +~~~~~~~~~~~~~~~~~~~~
    
    278
    +Consider   class Het a b | a -> b where
    
    279
    +              het :: m (f c) -> a -> m b
    
    280
    +
    
    281
    +           class GHet (a :: * -> *) (b :: * -> *) | a -> b
    
    282
    +           instance            GHet (K a) (K [a])
    
    283
    +           instance Het a b => GHet (K a) (K b)
    
    284
    +
    
    285
    +The two instances don't actually conflict on their fundeps,
    
    286
    +although it's pretty strange.  So they are both accepted. Now
    
    287
    +try   [W] GHet (K Int) (K Bool)
    
    288
    +This triggers fundeps from both instance decls;
    
    289
    +      [W] K Bool ~ K [a]
    
    290
    +      [W] K Bool ~ K beta
    
    291
    +And there's a risk of complaining about Bool ~ [a].  But in fact
    
    292
    +the Wanted matches the second instance, so we never get as far
    
    293
    +as the fundeps.
    
    294
    +
    
    295
    +#7875 is a case in point.
    
    296
    +-}
    
    297
    +
    
    298
    +doDictFunDepImprovement :: Cts -> TcS ImprovementResult
    
    299
    +-- (doDictFunDepImprovement inst_envs cts)
    
    300
    +--   * Generate the fundeps from interacting the
    
    301
    +--     top-level `inst_envs` with the constraints `cts`
    
    302
    +--   * Do the unifications and return any unsolved constraints
    
    303
    +-- See Note [Fundeps with instances, and equality orientation]
    
    304
    +-- foldrM :: (Foldable t, Monad m) => (a -> b -> m b) -> b -> t a -> m b
    
    305
    +doDictFunDepImprovement unsolved_wanteds
    
    306
    +  = do { inerts    <- getInertCans  -- The inert_dicts are all Givens
    
    307
    +       ; inst_envs <- getInstEnvs
    
    308
    +       ; (_, imp_res) <- foldM (do_one_dict inst_envs)
    
    309
    +                               (inert_dicts inerts, noopImprovement)
    
    310
    +                               unsolved_wanteds
    
    311
    +       ; return imp_res }
    
    312
    +
    
    313
    +do_one_dict :: InstEnvs
    
    314
    +            -> (DictMap DictCt, ImprovementResult)
    
    315
    +            -> Ct
    
    316
    +            -> TcS (DictMap DictCt, ImprovementResult)
    
    317
    +-- The `local_dicts` accumulator starts life as just the Givens, but
    
    318
    +--   as we encounter each Wanted we augment it. Result: each Wanted
    
    319
    +--   is interacted with all the Givens, and all prededing Wanteds.
    
    320
    +--   This is worst-case quadratic because we have to compare each
    
    321
    +--   constraint with all the others, to find all the pairwise interactions
    
    322
    +do_one_dict inst_envs (local_dicts, imp_res) (CDictCan dict_ct)
    
    323
    +  = do { (local_dicts1, imp_res1) <- do_one_local local_dicts dict_ct
    
    324
    +       ; if noImprovement imp_res1
    
    325
    +         then do { imp_res2 <- do_one_top inst_envs dict_ct
    
    326
    +                 ; return (local_dicts1, imp_res `plusImprovements` imp_res2) }
    
    327
    +         else      return (local_dicts1, imp_res `plusImprovements` imp_res1) }
    
    328
    +
    
    329
    +do_one_dict _ acc _  -- Non-DictCt constraints
    
    330
    +  = return acc
    
    331
    +
    
    332
    +do_one_top :: InstEnvs -> DictCt -> TcS ImprovementResult
    
    333
    +do_one_top inst_envs (DictCt { di_ev = ev, di_cls = cls, di_tys = xis })
    
    334
    +  = unifyFunDepWanteds ev eqns
    
    335
    +  where
    
    336
    +    eqns :: [FunDepEqn (CtLoc, RewriterSet)]
    
    337
    +    eqns = improveFromInstEnv inst_envs mk_ct_loc cls xis
    
    338
    +
    
    339
    +    dict_pred      = mkClassPred cls xis
    
    340
    +    dict_loc       = ctEvLoc ev
    
    341
    +    dict_origin    = ctLocOrigin dict_loc
    
    342
    +    dict_rewriters = ctEvRewriters ev
    
    343
    +
    
    344
    +    mk_ct_loc :: ClsInst  -- The instance decl
    
    345
    +              -> (CtLoc, RewriterSet)
    
    346
    +    mk_ct_loc ispec
    
    347
    +      = (dict_loc { ctl_origin = new_orig }, dict_rewriters)
    
    348
    +      where
    
    349
    +        inst_pred = mkClassPred cls (is_tys ispec)
    
    350
    +        inst_loc  = getSrcSpan (is_dfun ispec)
    
    351
    +        new_orig  = FunDepOrigin2 dict_pred dict_origin
    
    352
    +                                  inst_pred inst_loc
    
    353
    +
    
    354
    +do_one_local :: DictMap DictCt -> DictCt -> TcS (DictMap DictCt, ImprovementResult)
    
    355
    +-- Using functional dependencies, interact the unsolved Wanteds
    
    356
    +-- against each other and the inert Givens, to produce new equalities
    
    357
    +do_one_local locals dict_ct@(DictCt { di_cls = cls, di_ev = wanted_ev })
    
    358
    +    -- locals contains all the Givens and earlier Wanteds
    
    359
    +  = do { imp_res <- foldM do_interaction noopImprovement $
    
    360
    +                    findDictsByClass locals cls
    
    361
    +       ; return (addDict dict_ct locals, imp_res) }
    
    362
    +  where
    
    363
    +    wanted_pred = ctEvPred wanted_ev
    
    364
    +    wanted_loc  = ctEvLoc  wanted_ev
    
    365
    +
    
    366
    +    do_interaction :: (Cts,Bool) -> DictCt -> TcS (Cts,Bool)
    
    367
    +    do_interaction (new_eqs, unifs) (DictCt { di_ev = all_ev }) -- This can be Given or Wanted
    
    368
    +      = do { traceTcS "doLocalFunDepImprovement" $
    
    369
    +             vcat [ ppr wanted_ev
    
    370
    +                  , pprCtLoc wanted_loc, ppr (isGivenLoc wanted_loc)
    
    371
    +                  , pprCtLoc all_loc, ppr (isGivenLoc all_loc)
    
    372
    +                  , pprCtLoc deriv_loc, ppr (isGivenLoc deriv_loc) ]
    
    373
    +
    
    374
    +           ; (new_eqs1, unifs1) <- unifyFunDepWanteds wanted_ev $
    
    375
    +                                   improveFromAnother (deriv_loc, all_rewriters)
    
    376
    +                                                      all_pred wanted_pred
    
    377
    +           ; return (new_eqs1 `unionBags` new_eqs, unifs1 || unifs) }
    
    378
    +      where
    
    379
    +        all_pred  = ctEvPred all_ev
    
    380
    +        all_loc   = ctEvLoc all_ev
    
    381
    +        all_rewriters = ctEvRewriters all_ev
    
    382
    +        deriv_loc = wanted_loc { ctl_depth  = deriv_depth
    
    383
    +                               , ctl_origin = deriv_origin }
    
    384
    +        deriv_depth = ctl_depth wanted_loc `maxSubGoalDepth`
    
    385
    +                      ctl_depth all_loc
    
    386
    +        deriv_origin = FunDepOrigin1 wanted_pred
    
    387
    +                                     (ctLocOrigin wanted_loc)
    
    388
    +                                     (ctLocSpan wanted_loc)
    
    389
    +                                     all_pred
    
    390
    +                                     (ctLocOrigin all_loc)
    
    391
    +                                     (ctLocSpan all_loc)
    
    392
    +
    
    393
    +
    
    394
    +{-
    
    395
    +************************************************************************
    
    396
    +*                                                                      *
    
    397
    +              Emitting equalities arising from fundeps
    
    398
    +*                                                                      *
    
    399
    +************************************************************************
    
    400
    +-}
    
    401
    +
    
    402
    +type ImprovementResult = (Cts, Bool)
    
    403
    +  -- The Cts are the new equality constraints
    
    404
    +  -- The Bool is True if we unified any meta-ty-vars on when
    
    405
    +  --  generating those new equality constraints
    
    406
    +
    
    407
    +noopImprovement :: ImprovementResult
    
    408
    +noopImprovement = (emptyBag, False)
    
    409
    +
    
    410
    +noImprovement :: ImprovementResult -> Bool
    
    411
    +noImprovement (cts,unifs) = not unifs && isEmptyBag cts
    
    412
    +
    
    413
    +plusImprovements :: ImprovementResult -> ImprovementResult -> ImprovementResult
    
    414
    +plusImprovements (cts1,unif1) (cts2,unif2)
    
    415
    +  = (cts1 `unionBags` cts2, unif1 || unif2)
    
    416
    +
    
    417
    +
    
    418
    +unifyAndEmitFunDepWanteds :: CtEvidence  -- The work item
    
    419
    +                          -> [FunDepEqn (CtLoc, RewriterSet)]
    
    420
    +                          -> TcS Bool   -- True <=> some unification happened
    
    421
    +unifyAndEmitFunDepWanteds ev fd_eqns
    
    422
    +  = do { (new_eqs, unifs)  <- unifyFunDepWanteds ev fd_eqns
    
    423
    +
    
    424
    +       ;   -- Emit the deferred constraints
    
    425
    +           -- See Note [Work-list ordering] in GHC.Tc.Solved.Equality
    
    426
    +           --
    
    427
    +           -- All the constraints in `cts` share the same rewriter set so,
    
    428
    +           -- rather than looking at it one by one, we pass it to
    
    429
    +           -- extendWorkListChildEqs; just a small optimisation.
    
    430
    +       ; unless (isEmptyBag new_eqs) $
    
    431
    +         updWorkListTcS (extendWorkListChildEqs ev new_eqs)
    
    432
    +
    
    433
    +       ; return unifs }
    
    434
    +
    
    435
    +unifyFunDepWanteds :: CtEvidence  -- The work item
    
    436
    +                  -> [FunDepEqn (CtLoc, RewriterSet)]
    
    437
    +                  -> TcS ImprovementResult
    
    438
    +
    
    439
    +unifyFunDepWanteds _ [] = return noopImprovement -- common case noop
    
    440
    +-- See Note [FunDep and implicit parameter reactions]
    
    441
    +
    
    442
    +unifyFunDepWanteds ev fd_eqns
    
    443
    +  = do { (fresh_tvs_s, cts, unified_tvs) <- wrapUnifierX ev Nominal do_fundeps
    
    444
    +
    
    445
    +       -- Figure out if a "real" unification happened: See Note [unifyFunDeps]
    
    446
    +       ; let unif_happened = any is_old_tv unified_tvs
    
    447
    +             fresh_tvs     = mkVarSet (concat fresh_tvs_s)
    
    448
    +             is_old_tv tv  = not (tv `elemVarSet` fresh_tvs)
    
    449
    +
    
    450
    +       ; return (cts, unif_happened) }
    
    451
    +  where
    
    452
    +    do_fundeps :: UnifyEnv -> TcM [[TcTyVar]]
    
    453
    +    do_fundeps env = mapM (do_one env) fd_eqns
    
    454
    +
    
    455
    +    do_one :: UnifyEnv -> FunDepEqn (CtLoc, RewriterSet) -> TcM [TcTyVar]
    
    456
    +    do_one uenv (FDEqn { fd_qtvs = tvs, fd_eqs = eqs, fd_loc = (loc, rewriters) })
    
    457
    +      = do { (fresh_tvs, eqs') <- instantiateFunDepEqn tvs (reverse eqs)
    
    458
    +                     -- (reverse eqs): See Note [Reverse order of fundep equations]
    
    459
    +           ; uPairsTcM env_one eqs'
    
    460
    +           ; return fresh_tvs }
    
    461
    +      where
    
    462
    +        env_one = uenv { u_rewriters = u_rewriters uenv S.<> rewriters
    
    463
    +                       , u_loc       = loc }
    
    464
    +
    
    465
    +instantiateFunDepEqn :: [TyVar] -> [TypeEqn] -> TcM ([TcTyVar], [TypeEqn])
    
    466
    +instantiateFunDepEqn tvs eqs
    
    467
    +  | null tvs
    
    468
    +  = return ([], eqs)
    
    469
    +  | otherwise
    
    470
    +  = do { TcM.traceTc "emitFunDepWanteds 2" (ppr tvs $$ ppr eqs)
    
    471
    +       ; (tvs', subst) <- instFlexiXTcM emptySubst tvs  -- Takes account of kind substitution
    
    472
    +       ; return (tvs', map (subst_pair subst) eqs) }
    
    473
    +  where
    
    474
    +    subst_pair subst (Pair ty1 ty2)
    
    475
    +       = Pair (substTyUnchecked subst' ty1) ty2
    
    476
    +              -- ty2 does not mention fd_qtvs, so no need to subst it.
    
    477
    +              -- See GHC.Tc.Instance.Fundeps Note [Improving against instances]
    
    478
    +              --     Wrinkle (1)
    
    479
    +       where
    
    480
    +         subst' = extendSubstInScopeSet subst (tyCoVarsOfType ty1)
    
    481
    +                  -- The free vars of ty1 aren't just fd_qtvs: ty1 is the result
    
    482
    +                  -- of matching with the [W] constraint. So we add its free
    
    483
    +                  -- vars to InScopeSet, to satisfy substTy's invariants, even
    
    484
    +                  -- though ty1 will never (currently) be a poytype, so this
    
    485
    +                  -- InScopeSet will never be looked at.
    
    486
    +

  • compiler/GHC/Tc/Solver/Monad.hs
    ... ... @@ -105,10 +105,9 @@ module GHC.Tc.Solver.Monad (
    105 105
     
    
    106 106
         -- Unification
    
    107 107
         wrapUnifierX, wrapUnifierTcS, unifyFunDeps, uPairsTcM, unifyForAllBody,
    
    108
    -    unifyFunDepWanteds, unifyAndEmitFunDepWanteds,
    
    109 108
     
    
    110 109
         -- MetaTyVars
    
    111
    -    newFlexiTcSTy, instFlexiX,
    
    110
    +    newFlexiTcSTy, instFlexiX, instFlexiXTcM,
    
    112 111
         cloneMetaTyVar,
    
    113 112
         tcInstSkolTyVarsX,
    
    114 113
     
    
    ... ... @@ -129,8 +128,7 @@ module GHC.Tc.Solver.Monad (
    129 128
         pprEq,
    
    130 129
     
    
    131 130
         -- Enforcing invariants for type equalities
    
    132
    -    checkTypeEq,
    
    133
    -    instantiateFunDepEqn
    
    131
    +    checkTypeEq
    
    134 132
     ) where
    
    135 133
     
    
    136 134
     import GHC.Prelude
    
    ... ... @@ -2235,83 +2233,6 @@ solverDepthError loc ty
    2235 2233
       where
    
    2236 2234
         depth = ctLocDepth loc
    
    2237 2235
     
    
    2238
    -{-
    
    2239
    -************************************************************************
    
    2240
    -*                                                                      *
    
    2241
    -              Emitting equalities arising from fundeps
    
    2242
    -*                                                                      *
    
    2243
    -************************************************************************
    
    2244
    --}
    
    2245
    -
    
    2246
    -unifyAndEmitFunDepWanteds :: CtEvidence  -- The work item
    
    2247
    -                          -> [FunDepEqn (CtLoc, RewriterSet)]
    
    2248
    -                          -> TcS Bool   -- True <=> some unification happened
    
    2249
    -unifyAndEmitFunDepWanteds ev fd_eqns
    
    2250
    -  = do { (new_eqs, unifs)  <- unifyFunDepWanteds ev fd_eqns
    
    2251
    -
    
    2252
    -       ;   -- Emit the deferred constraints
    
    2253
    -           -- See Note [Work-list ordering] in GHC.Tc.Solved.Equality
    
    2254
    -           --
    
    2255
    -           -- All the constraints in `cts` share the same rewriter set so,
    
    2256
    -           -- rather than looking at it one by one, we pass it to
    
    2257
    -           -- extendWorkListChildEqs; just a small optimisation.
    
    2258
    -       ; unless (isEmptyBag new_eqs) $
    
    2259
    -         updWorkListTcS (extendWorkListChildEqs ev new_eqs)
    
    2260
    -
    
    2261
    -       ; return unifs }
    
    2262
    -
    
    2263
    -unifyFunDepWanteds :: CtEvidence  -- The work item
    
    2264
    -                  -> [FunDepEqn (CtLoc, RewriterSet)]
    
    2265
    -                  -> TcS (Cts, Bool)   -- True <=> some unification happened
    
    2266
    -
    
    2267
    -unifyFunDepWanteds _ [] = return (emptyBag, False) -- common case noop
    
    2268
    --- See Note [FunDep and implicit parameter reactions]
    
    2269
    -
    
    2270
    -unifyFunDepWanteds ev fd_eqns
    
    2271
    -  = do { (fresh_tvs_s, cts, unified_tvs) <- wrapUnifierX ev Nominal do_fundeps
    
    2272
    -
    
    2273
    -       -- Figure out if a "real" unification happened: See Note [unifyFunDeps]
    
    2274
    -       ; let unif_happened = any is_old_tv unified_tvs
    
    2275
    -             fresh_tvs     = mkVarSet (concat fresh_tvs_s)
    
    2276
    -             is_old_tv tv  = not (tv `elemVarSet` fresh_tvs)
    
    2277
    -
    
    2278
    -       ; return (cts, unif_happened) }
    
    2279
    -  where
    
    2280
    -    do_fundeps :: UnifyEnv -> TcM [[TcTyVar]]
    
    2281
    -    do_fundeps env = mapM (do_one env) fd_eqns
    
    2282
    -
    
    2283
    -    do_one :: UnifyEnv -> FunDepEqn (CtLoc, RewriterSet) -> TcM [TcTyVar]
    
    2284
    -    do_one uenv (FDEqn { fd_qtvs = tvs, fd_eqs = eqs, fd_loc = (loc, rewriters) })
    
    2285
    -      = do { (fresh_tvs, eqs') <- instantiateFunDepEqn tvs (reverse eqs)
    
    2286
    -                     -- (reverse eqs): See Note [Reverse order of fundep equations]
    
    2287
    -           ; uPairsTcM env_one eqs'
    
    2288
    -           ; return fresh_tvs }
    
    2289
    -      where
    
    2290
    -        env_one = uenv { u_rewriters = u_rewriters uenv S.<> rewriters
    
    2291
    -                       , u_loc       = loc }
    
    2292
    -
    
    2293
    -instantiateFunDepEqn :: [TyVar] -> [TypeEqn] -> TcM ([TcTyVar], [TypeEqn])
    
    2294
    -instantiateFunDepEqn tvs eqs
    
    2295
    -  | null tvs
    
    2296
    -  = return ([], eqs)
    
    2297
    -  | otherwise
    
    2298
    -  = do { TcM.traceTc "emitFunDepWanteds 2" (ppr tvs $$ ppr eqs)
    
    2299
    -       ; (tvs', subst) <- instFlexiXTcM emptySubst tvs  -- Takes account of kind substitution
    
    2300
    -       ; return (tvs', map (subst_pair subst) eqs) }
    
    2301
    -  where
    
    2302
    -    subst_pair subst (Pair ty1 ty2)
    
    2303
    -       = Pair (substTyUnchecked subst' ty1) ty2
    
    2304
    -              -- ty2 does not mention fd_qtvs, so no need to subst it.
    
    2305
    -              -- See GHC.Tc.Instance.Fundeps Note [Improving against instances]
    
    2306
    -              --     Wrinkle (1)
    
    2307
    -       where
    
    2308
    -         subst' = extendSubstInScopeSet subst (tyCoVarsOfType ty1)
    
    2309
    -                  -- The free vars of ty1 aren't just fd_qtvs: ty1 is the result
    
    2310
    -                  -- of matching with the [W] constraint. So we add its free
    
    2311
    -                  -- vars to InScopeSet, to satisfy substTy's invariants, even
    
    2312
    -                  -- though ty1 will never (currently) be a poytype, so this
    
    2313
    -                  -- InScopeSet will never be looked at.
    
    2314
    -
    
    2315 2236
     {-
    
    2316 2237
     ************************************************************************
    
    2317 2238
     *                                                                      *
    

  • compiler/GHC/Tc/Solver/Solve.hs
    ... ... @@ -15,6 +15,7 @@ module GHC.Tc.Solver.Solve (
    15 15
     import GHC.Prelude
    
    16 16
     
    
    17 17
     import GHC.Tc.Solver.Dict
    
    18
    +import GHC.Tc.Solver.FunDeps( doDictFunDepImprovement )
    
    18 19
     import GHC.Tc.Solver.Equality( solveEquality )
    
    19 20
     import GHC.Tc.Solver.Irred( solveIrred )
    
    20 21
     import GHC.Tc.Solver.Rewrite( rewrite, rewriteType )
    
    ... ... @@ -119,13 +120,13 @@ simplify_loop n limit definitely_redo_implications
    119 120
                                 , int (lengthBag simples) <+> text "simples to solve" ])
    
    120 121
            ; traceTcS "simplify_loop: wc =" (ppr wc)
    
    121 122
     
    
    122
    -       ; (unifs1, wc1) <- reportUnifications $  -- See Note [Superclass iteration]
    
    123
    -                          solveSimpleWanteds simples
    
    123
    +       ; (n_unifs, wc1) <- reportUnifications $  -- See Note [Superclass iteration]
    
    124
    +                           solveSimpleWanteds simples
    
    124 125
                     -- Any insoluble constraints are in 'simples' and so get rewritten
    
    125 126
                     -- See Note [Rewrite insolubles] in GHC.Tc.Solver.InertSet
    
    126 127
     
    
    127 128
            ; wc2 <- if not definitely_redo_implications  -- See Note [Superclass iteration]
    
    128
    -                   && unifs1 == 0                    -- for this conditional
    
    129
    +                   && n_unifs == 0                   -- for this conditional
    
    129 130
                        && isEmptyBag (wc_impl wc1)
    
    130 131
                     then return (wc { wc_simple = wc_simple wc1 })  -- Short cut
    
    131 132
                     else do { implics2 <- solveNestedImplications $
    
    ... ... @@ -207,10 +208,19 @@ maybe_simplify_again n limit unif_happened wc@(WC { wc_simple = simples })
    207 208
     
    
    208 209
         try_fundeps :: TcS (Maybe NextAction)
    
    209 210
         try_fundeps
    
    210
    -      = do { (new_eqs, unifs) <- doDictFunDepImprovement simples
    
    211
    -           ; if null new_eqs && not unifs
    
    211
    +      = do { (new_eqs, unifs1) <- doDictFunDepImprovement simples
    
    212
    +           ; if null new_eqs && not unifs1
    
    212 213
                  then return Nothing
    
    213
    -             else return (Just (NA_TryAgain (wc `addSimples` new_eqs) unifs)) }
    
    214
    +             else
    
    215
    +        -- We solve new_eqs immediately, hoping to get some unifications
    
    216
    +        -- If instead we just added them to `wc` we'll iterate and (in case when
    
    217
    +        -- that doesn't solve it) we'll add the same constraint again... loop!
    
    218
    +        do { traceTcS "try_fundeps" (ppr unifs1 $$ ppr new_eqs)
    
    219
    +           ; (n_unifs2, _wc) <- reportUnifications $
    
    220
    +                                solveSimpleWanteds new_eqs
    
    221
    +           ; if (unifs1 || n_unifs2 > 0)
    
    222
    +             then return (Just (NA_TryAgain wc True))
    
    223
    +             else return Nothing } }
    
    214 224
     
    
    215 225
     {- Note [Superclass iteration]
    
    216 226
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

  • compiler/ghc.cabal.in
    ... ... @@ -854,6 +854,7 @@ Library
    854 854
             GHC.Tc.Solver.Irred
    
    855 855
             GHC.Tc.Solver.Equality
    
    856 856
             GHC.Tc.Solver.Dict
    
    857
    +        GHC.Tc.Solver.FunDeps
    
    857 858
             GHC.Tc.Solver.Monad
    
    858 859
             GHC.Tc.Solver.Types
    
    859 860
             GHC.Tc.TyCl