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

Commits:

2 changed files:

Changes:

  • compiler/GHC/Tc/Solver/Dict.hs
    ... ... @@ -10,7 +10,7 @@ module GHC.Tc.Solver.Dict (
    10 10
       solveCallStack,    -- For GHC.Tc.Solver
    
    11 11
     
    
    12 12
       -- * Functional dependencies
    
    13
    -  doTopFunDepImprovement, doLocalFunDepImprovement
    
    13
    +  doDictFunDepImprovement
    
    14 14
       ) where
    
    15 15
     
    
    16 16
     import GHC.Prelude
    
    ... ... @@ -59,6 +59,7 @@ import GHC.Driver.DynFlags
    59 59
     
    
    60 60
     import qualified GHC.LanguageExtensions as LangExt
    
    61 61
     
    
    62
    +import Data.Foldable( foldrM )
    
    62 63
     import Data.Maybe ( listToMaybe, mapMaybe, isJust )
    
    63 64
     import Data.Void( Void )
    
    64 65
     
    
    ... ... @@ -1630,92 +1631,93 @@ as the fundeps.
    1630 1631
     #7875 is a case in point.
    
    1631 1632
     -}
    
    1632 1633
     
    
    1633
    -doTopFunDepImprovement :: Bag DictCt -> TcS (Cts, Bool)
    
    1634
    --- (doFunDeps inst_envs cts)
    
    1634
    +doDictFunDepImprovement :: Cts -> TcS (Cts, Bool)
    
    1635
    +-- (doDictFunDepImprovement inst_envs cts)
    
    1635 1636
     --   * Generate the fundeps from interacting the
    
    1636 1637
     --     top-level `inst_envs` with the constraints `cts`
    
    1637 1638
     --   * Do the unifications and return any unsolved constraints
    
    1638 1639
     -- See Note [Fundeps with instances, and equality orientation]
    
    1639
    -doTopFunDepImprovement cts
    
    1640
    -  = do { inst_envs <- getInstEnvs
    
    1641
    -       ; do_dict_fundeps (do_one inst_envs) cts }
    
    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
    
    1642 1664
       where
    
    1643
    -    do_one :: InstEnvs -> DictCt -> TcS (Cts, Bool)
    
    1644
    -    do_one inst_envs (DictCt { di_ev = ev, di_cls = cls, di_tys = xis })
    
    1645
    -      = unifyFunDepWanteds ev eqns
    
    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)
    
    1646 1677
           where
    
    1647
    -        eqns :: [FunDepEqn (CtLoc, RewriterSet)]
    
    1648
    -        eqns = improveFromInstEnv inst_envs mk_ct_loc cls xis
    
    1649
    -
    
    1650
    -        dict_pred      = mkClassPred cls xis
    
    1651
    -        dict_loc       = ctEvLoc ev
    
    1652
    -        dict_origin    = ctLocOrigin dict_loc
    
    1653
    -        dict_rewriters = ctEvRewriters ev
    
    1654
    -
    
    1655
    -        mk_ct_loc :: ClsInst  -- The instance decl
    
    1656
    -                  -> (CtLoc, RewriterSet)
    
    1657
    -        mk_ct_loc ispec
    
    1658
    -          = (dict_loc { ctl_origin = new_orig }, dict_rewriters)
    
    1659
    -          where
    
    1660
    -            inst_pred = mkClassPred cls (is_tys ispec)
    
    1661
    -            inst_loc  = getSrcSpan (is_dfun ispec)
    
    1662
    -            new_orig  = FunDepOrigin2 dict_pred dict_origin
    
    1663
    -                                      inst_pred inst_loc
    
    1664
    -
    
    1665
    -doLocalFunDepImprovement :: Bag DictCt -> TcS (Cts,Bool)
    
    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)
    
    1666 1684
     -- Using functional dependencies, interact the unsolved Wanteds
    
    1667 1685
     -- against each other and the inert Givens, to produce new equalities
    
    1668
    -doLocalFunDepImprovement wanted
    
    1669
    -  = do { inerts <- getInertCans  -- The inert_dicts are all Givens
    
    1670
    -       ; let all_dicts :: DictMap DictCt  -- Both Givens and Wanteds
    
    1671
    -             all_dicts = foldr addDict (inert_dicts inerts) wanted
    
    1672
    -       ; do_dict_fundeps (do_one all_dicts) wanted }
    
    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) }
    
    1673 1691
       where
    
    1674
    -    -- all_dicts are all the Givens and all the Wanteds
    
    1675
    -    do_one all_dicts (DictCt { di_cls = cls, di_ev = wanted_ev })
    
    1676
    -      = do_dict_fundeps do_interaction (findDictsByClass all_dicts cls)
    
    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) }
    
    1677 1707
           where
    
    1678
    -        wanted_pred = ctEvPred wanted_ev
    
    1679
    -        wanted_loc  = ctEvLoc  wanted_ev
    
    1680
    -
    
    1681
    -        do_interaction :: DictCt -> TcS (Cts,Bool)
    
    1682
    -        do_interaction (DictCt { di_ev = all_ev })  -- This can be Given or Wanted
    
    1683
    -          = do { traceTcS "doLocalFunDepImprovement" $
    
    1684
    -                 vcat [ ppr wanted_ev
    
    1685
    -                      , pprCtLoc wanted_loc, ppr (isGivenLoc wanted_loc)
    
    1686
    -                      , pprCtLoc all_loc, ppr (isGivenLoc all_loc)
    
    1687
    -                      , pprCtLoc deriv_loc, ppr (isGivenLoc deriv_loc) ]
    
    1688
    -
    
    1689
    -               ; unifyFunDepWanteds wanted_ev $
    
    1690
    -                 improveFromAnother (deriv_loc, all_rewriters)
    
    1691
    -                                    all_pred wanted_pred }
    
    1692
    -          where
    
    1693
    -            all_pred  = ctEvPred all_ev
    
    1694
    -            all_loc   = ctEvLoc all_ev
    
    1695
    -            all_rewriters = ctEvRewriters all_ev
    
    1696
    -            deriv_loc = wanted_loc { ctl_depth  = deriv_depth
    
    1697
    -                                   , ctl_origin = deriv_origin }
    
    1698
    -            deriv_depth = ctl_depth wanted_loc `maxSubGoalDepth`
    
    1699
    -                          ctl_depth all_loc
    
    1700
    -            deriv_origin = FunDepOrigin1 wanted_pred
    
    1701
    -                                         (ctLocOrigin wanted_loc)
    
    1702
    -                                         (ctLocSpan wanted_loc)
    
    1703
    -                                         all_pred
    
    1704
    -                                         (ctLocOrigin all_loc)
    
    1705
    -                                         (ctLocSpan all_loc)
    
    1706
    -
    
    1707
    -do_dict_fundeps :: (DictCt -> TcS (Cts,Bool)) -> Bag DictCt -> TcS (Cts,Bool)
    
    1708
    -do_dict_fundeps do_dict_fundep cts
    
    1709
    -  = foldr do_one (return (emptyBag, False)) cts
    
    1710
    -  where
    
    1711
    -    do_one :: DictCt -> TcS (Cts,Bool) -> TcS (Cts,Bool)
    
    1712
    -    do_one dict_ct do_rest
    
    1713
    -      = -- assert (not (isGiven (dictCtEvidence dict_ct)) $
    
    1714
    -        do { (cts1, unifs1) <- do_dict_fundep dict_ct
    
    1715
    -           ; if isEmptyBag cts1 && not unifs1
    
    1716
    -             then do_rest  -- Common case
    
    1717
    -             else do { (cts2, unifs2) <- do_rest
    
    1718
    -                     ; return (cts1 `unionBags` cts2, unifs1 || unifs2) } }
    
    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)
    
    1719 1721
     
    
    1720 1722
     
    
    1721 1723
     {- *********************************************************************
    

  • compiler/GHC/Tc/Solver/Solve.hs
    ... ... @@ -205,18 +205,9 @@ maybe_simplify_again n limit unif_happened wc@(WC { wc_simple = simples })
    205 205
           | otherwise
    
    206 206
           = return Nothing
    
    207 207
     
    
    208
    -    dicts :: Bag DictCt
    
    209
    -    dicts = mapMaybeBag is_dict simples
    
    210
    -          where
    
    211
    -            is_dict (CDictCan d) = Just d
    
    212
    -            is_dict _            = Nothing
    
    213
    -
    
    214 208
         try_fundeps :: TcS (Maybe NextAction)
    
    215 209
         try_fundeps
    
    216
    -      = do { (new_eqs1, unifs1) <- doTopFunDepImprovement dicts
    
    217
    -           ; (new_eqs2, unifs2) <- doLocalFunDepImprovement dicts
    
    218
    -           ; let new_eqs = new_eqs1 `unionBags` new_eqs2
    
    219
    -                 unifs   = unifs1 || unifs2
    
    210
    +      = do { (new_eqs, unifs) <- doDictFunDepImprovement simples
    
    220 211
                ; if null new_eqs && not unifs
    
    221 212
                  then return Nothing
    
    222 213
                  else return (Just (NA_TryAgain (wc `addSimples` new_eqs) unifs)) }